package com.example.demo.API;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import com.example.demo.common.AjaxResult;
import com.example.demo.common.AppVariable;
import com.example.demo.common.PasswordUtils;
import com.example.demo.common.UserSessionUtils;
import com.example.demo.entity.Userinfo;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.soap.SAAJResult;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created with IntelliJ IEDA.
 * Description:
 * User:86186
 * Date:2023-10-21
 * Time:22:17
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;

    /**
     * 用户登录
     */
    @RequestMapping("/login")
    public AjaxResult login(String username, String password,String code, HttpServletRequest request){
        // 1.非空校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return AjaxResult.fail(-1, "用户名或密码为空!");
        }

        Userinfo userinfo = userMapper.getUserByName(username);
        if (userinfo == null) {
            return AjaxResult.fail(-2, "账号未注册!");
        }
        //拿到验证码
        String imgCode = UserSessionUtils.getImgCode(request);
        System.out.println("code+" + code);
        System.out.println("imgcode+" +imgCode);
        if (!code.equals(imgCode)){
            return AjaxResult.fail(-3,"验证码输入错误");
        }
        // 2.判断密码是否相等
        if (PasswordUtils.check(password,userinfo.getPassword()) && userinfo.getState() != 6){
            // 登陆成功
            // 将用户存储到 session 中
            // 需要创建会话，所以设为 true
            HttpSession session = request.getSession();
            session.setAttribute(AppVariable.USER_SESSION_KEY,userinfo);

            userinfo.setPassword("");//返回前端前，隐藏敏感信息
            userMapper.updateUserStatefoById(1,userinfo.getId());
            return AjaxResult.success(userinfo);
        }else {
            /**
             * 密码错误就将 state 加一,给定最大允许密码错误次数，
             * 当 state - 1 大于最大次数时就等待 60s
             * state default 为1
             */
            int maxAttempts = 4;// 最大允许错误次数
            int waitTime = AppVariable.WAIT_TIME;//等待 60s
            if (userinfo.getState() > 5){
                // 此时用户以及超出最大允许错误次数,需要等待60s
                LocalDateTime localDateTime = LocalDateTime.now();
                LocalDateTime postTime = localDateTime.plusSeconds(waitTime);
                Duration duration = Duration.between(localDateTime, postTime);
                long delay = duration.toMillis();

                Timer timer = new Timer();
                if (userinfo.getState() != 1){
                    timer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            userMapper.updateUserStatefoById(1, userinfo.getId());
                        }
                    }, delay);
                    return AjaxResult.fail(-4, "密码错误次数过多，请等待 " + waitTime + " 秒后再试！");
                }
            }else {
                // 密码输入错误
                userMapper.updateUserStatefoById(userinfo.getState() + 1,userinfo.getId());
                return AjaxResult.fail(-5, "密码错误，剩余尝试次数：" + (maxAttempts - userinfo.getState() + 1));
            }
        }

        return AjaxResult.success(1);
    }

    /**
     * 注册
     * @param userinfo
     * @return
     */
    @RequestMapping("/reg")
    public AjaxResult addUser(Userinfo userinfo){
        // 非空校验
        if (userinfo == null ||
                !StringUtils.hasLength(userinfo.getUsername()) ||
                !StringUtils.hasLength(userinfo.getPassword())){
            return AjaxResult.fail(-1,"非法参数");
        }
        // 密码加盐加密
        userinfo.setPassword(PasswordUtils.encrypt(userinfo.getPassword()));
        return AjaxResult.success(userMapper.reg(userinfo));
    }


    /**
     *  登录之前添加验证码.
     */
    @GetMapping("/getcode")
    public void getCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 通知浏览器不要缓存
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setHeader("expires", "0");


        // 生成一个验证码图片                                                // 宽          高   几位数的验证码     干扰点
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(116, 36, 4, 10);

        // 拿到图片生成的验证码
        String code = circleCaptcha.getCode();
        System.out.println("code: " + code);

        // 每调用一次此方法, 就会生成新的 code, 存到 session[redis] 中
        HttpSession session = request.getSession(true);
        session.setAttribute(AppVariable.LOGIN_CHECK_CODE, code);

        // 拿到流对象
        ServletOutputStream outputStream = response.getOutputStream();
        if (outputStream != null) {
            // 通过输出流输出给前端
            circleCaptcha.write(outputStream);
            // 关闭资源
            outputStream.close();
        }
    }
    /**
     * 得到用户信息
     */
    @RequestMapping("/getUsernfo")
    public AjaxResult getUsernfo(HttpServletRequest request){
        Userinfo userinfo = UserSessionUtils.getSessionUser(request);
        if (userinfo == null || !StringUtils.hasLength(userinfo.getUsername()) || userinfo.getId() <= 0){
            return AjaxResult.fail(-2,"用户为空，请重新登录!");
        }
        // 去除敏感数据(密码)
        userinfo.setPassword("");
        return AjaxResult.success(userinfo);
    }

}
